/**
 * 代理模式经典案例：事件代理，虚拟代理，缓存代理、保护代理
 */

// 事件代理：经典场景-给一系列子元素绑定事件，利用事件冒泡，将事件注册在父元素上


// 虚拟代理: 图片预加载
// 不使用代理模式：存在的问题-preLoadImage要做1. 图片的加载 2. Dom层面的操作
class PreLoadImage {
    // 占位图url地址
    static LOADING_IMG = 'xxx';

    constructor(imgNode) {
        // 获取该实例对应的Dom节点
        this.imgNode = imgNode;
    }

    // 该方法用于设置具体的图片地址
    setSrc(targetUrl){
        // img节点初始化时展示的是一个占位图
        this.imgNode.src = PreLoadImage.LOADING_IMG;
        // 创建一个加载图片的img实例
        const image = new Image();
        // 监听目标图片加载情况，完成试再将dom上的img的src设置为目标url
        image.onload = () => {
            this.imgNode.src = targetUrl;
        }
        image.src = targetUrl;
    }
}

// 使用代理模式
// 获取图片，设置地址
class PreLoadImage {
    constructor(imgNode) {
        this.imgNode = imgNode;
    }

    setUrl(url) {
        this.imgNode.src = url;
    }
}
// 代理：实现了预加载的实现，不直接访问真实img 节点
class ProxyImage {
    static LOADING_IMG = 'xxx';

    constructor(targetImage) {
        // 目标image，即PreLoadImage对象实例
        this.targetImage = targetImage;
    }
    // 该方法主要操作虚拟Image，完成图片加载
    setUrl(targetUrl) {
        // 显示占位图
        this.targetImage.setSrc(ProxyImage.LOADING_IMG);
        // image对象加载图片
        const image = new Image();
        image.onload = () => {
            // 加载完成之后，真实的img节点直接从缓存获取图片
            this.targetImage.setSrc(targetUrl)
        }
        image.src = targetUrl;
    }
}

// 缓存代理： 应用于计算量较大的场景，当用到某个已经计算过的值，不需要再耗时进行二次计算，直接从内存中取，简而言之，就是空间换时间
// 经典案例： 将传入的所有参数求和
const addAll = function() {
    let result = 0;
    for (let i =0; i<arguments.length; i++) {
        result += arguments[i];
    }
    return result;
}
// 使用缓存代理
const proxyAddAll = (function(){
    // 求和结果缓存
    let resultCache = {};
    return function() {
        // 保存参数key
        let arg = Array.prototype.join.call(arguments, ',');
        if (arg in resultCache) {
            return resultCache[arg]
        }
        return resultCache[arg] = addAll(...arguments)
    }
})();
proxyAddAll(1,2,3,4);